﻿using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Threading;
using T.ServiceComponent.Log.Client;
using T.ServiceComponent.Log.SPI;
using System.Linq;

namespace T.FAS.Runtime.DataAccess.Common
{
    public class LogClientTools
    {
        private readonly static object s_lock = new object();
        private readonly static ConcurrentQueue<ILog> s_msgCache = new ConcurrentQueue<ILog>();
        private readonly static LogLocalClient s_logClient = new LogLocalClient(); 
        public static ILogService LogService
        {
            get
            {
                // return HSFService.Proxy<ILogService>();
                return null;
            }
        }
        private readonly static int s_logBatchCount = 300;
        private readonly static int s_sleepDuration = 500;
        private static bool s_isRunning = false;
        private static CancellationTokenSource s_cts;

        public static bool IsRunning { get { return s_isRunning; } }

        public static void StartLog()
        {
            lock (s_lock)
            {
                if (!s_isRunning)
                {
                    s_cts = new CancellationTokenSource();
                    SendMsg();
                    s_isRunning = true;
                }
            }
        }

        public static void Stop()
        {
            s_cts.Cancel();
        }

        public static void Put(ILog log)
        {
            if (log != null)
                s_msgCache.Enqueue(log);
        }

        private static void SendMsg()
        {
            Task task = new Task((arg) =>
            {
                while (!s_cts.IsCancellationRequested)
                {
                    Thread.Sleep(s_sleepDuration);
                    if (s_msgCache != null && s_msgCache.Count > 0)
                    {
                        ILog[] logs = TryGetMsg(s_logBatchCount);
                        //logClient在org环境不好用，推不出消息。优先使用logService
                        if (LogService != null)
                            LogService.SendMsgs(logs.ToList());
                        else
                            s_logClient.SendLogs(logs);
                    }
                }
            }, null, s_cts.Token, TaskCreationOptions.LongRunning);
            task.ContinueWith((t) => MsgTaskWatcher());
            task.Start();
        }

        private static void MsgTaskWatcher()
        {
            if (s_cts != null && !s_cts.IsCancellationRequested)
                SendMsg();
        }

        private static ILog[] TryGetMsg(int count)
        {
            if (s_msgCache == null || s_msgCache.Count == 0)
                return null;
            List<ILog> logs = new List<ILog>();
            for (int i = 0; i < count; i++)
            {
                if (s_msgCache.Count > 0)
                {
                    if (s_msgCache.TryDequeue(out ILog log))
                    {
                        logs.Add(log);
                    }
                }
            }
            return logs.ToArray();
        }
    }
}